package cn.kow.kmall.interceptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import cn.kow.kmall.core.response.KmallResult;
import cn.kow.kmall.common.enums.KmallResultEnum;
import cn.kow.kmall.core.util.JwtTokenUtils;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author kow
 */
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {

    @Autowired
    private ObjectMapper objectMapper;

    @Value("${jwt.secret}")
    private String secret;

    /**
     * 该方法在action执行前执行，可以实现对数据的预处理，
     * 比如：编码、安全控制等。如果方法返回true，则继续执行action。
     */
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        try {
            String token = getRequestToken(httpServletRequest);
            if (StringUtils.isEmpty(token)) {
                httpServletResponse.setContentType("application/json;charset=UTF-8");
                httpServletResponse.getWriter().write(objectMapper.writeValueAsString(KmallResult.build(KmallResultEnum.UNAUTHORIZED)));
                return false;
            }
            // token校验
            Claims claims = JwtTokenUtils.verify(token,secret);
            if (claims == null) {
                httpServletResponse.setContentType("application/json;charset=UTF-8");
                httpServletResponse.getWriter().write(objectMapper.writeValueAsString(KmallResult.build(KmallResultEnum.UNAUTHORIZED)));
                return false;
            }
            String username = claims.getSubject();
            Long uid = Long.valueOf(claims.get("uid").toString());
            String openid = claims.get("openid").toString();
            httpServletRequest.setAttribute("uid", uid);
            httpServletRequest.setAttribute("openid", openid);
            log.info("uid={}, openid={}", uid, openid);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            httpServletResponse.setContentType("application/json;charset=UTF-8");
            httpServletResponse.getWriter().write(objectMapper.writeValueAsString(KmallResult.build(KmallResultEnum.UNAUTHORIZED)));
            return false;
        }
    }

    /**
     * 该方法在action执行后，生成视图前执行。在这里，我们有机会修改视图层数据。
     */
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    /**
     * 最后执行，通常用于释放资源，处理异常。我们可以根据ex是否为空，来进行相关的异常处理。
     * 因为我们在平时处理异常时，都是从底层向上抛出异常，最后到了spring框架从而到了这个方法中。
     */
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }

    /**
     * 获取请求的token
     */
    private String getRequestToken(HttpServletRequest httpRequest) {
        //从header中获取token
        String token = httpRequest.getHeader("X-WeMall-Token");

        //如果header中不存在token，则从参数中获取token
        if (StringUtils.isBlank(token)) {
            token = httpRequest.getParameter("token");
        }

        return token;
    }
}
